package spring.lottery.common.util;

import cn.hutool.jwt.JWT;

import java.security.Key;
import java.util.Date;
import java.util.Map;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.InvalidKeyException;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

/**
 * 使用jwt令牌来验证是否登录了
 */
@Slf4j
public class JWTUtil {

    private static ObjectMapper objectMapper = new ObjectMapper();

    //1天
    private static final long EXPIRATION = 60 * 60 * 60 * 1000;

//     将密钥编码为Base64字符串。
//    Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
//    String secretString = Encoders.BASE64.encode(key.getEncoded());

    //将h256算法生成的密钥对象转为base64字符串格式 这样每次服务启动的key都不相同
//    private static final String SECRET = Encoders.BASE64.encode(Keys.secretKeyFor(SignatureAlgorithm.HS256).getEncoded());
    //在将这个字符串解密为密钥对象Key，用来表示生成的令牌的算法
    private static final Key SECRET_KEY = Keys.hmacShaKeyFor(Keys.secretKeyFor(SignatureAlgorithm.HS256).getEncoded());

    public static String getToken(Map<String, Object> claims) {

        //签名算法
        String jwt = null;
        try {
            jwt = Jwts.builder()
                    .setClaims(claims)             // 自定义内容(载荷)
                    .signWith(SECRET_KEY)         // 签名算法
                    .setIssuedAt(new Date())      // 设置签发时间
                    .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION)) // 设置过期时间
                    .compact();
            return jwt;
        } catch (InvalidKeyException e) {
            log.error("jwt令牌生成失败： {}", e.getMessage(), e);
            return null;
        }
    }

    //将类转换为Map对象
    public static String getToken(Object claims) {
        try {
            String s = objectMapper.writeValueAsString(claims);

            Map<String, Object> map = objectMapper.readValue(s, Map.class);

            return getToken(map);

        } catch (JsonMappingException e) {
            log.error("在反序列化对象的时候出现了错误: {}", e.getMessage(), e);
            return null;
        } catch (JsonProcessingException e) {
            log.error("在序列化对象的时候出现了错误: {}", e.getMessage(), e);
            return null;
        }
    }

    public static Claims parseToken(String token) {
        if (!StringUtils.hasLength(token)) {
            return null;
        }
        JwtParser build = null;
        try {
            //setExpiration(null); 过期时间
            //setIssuedAt(null); 签发时间
            build = Jwts.parserBuilder().setSigningKey(SECRET_KEY).build();
            return build.parseClaimsJws(token).getBody();
        } catch (Exception e) {

            log.error("jwt令牌解析失败： {}", e.getMessage(), e);
            return null;
        }
    }
}
